﻿#region using
using System;
using System.Collections.Generic;
using System.Text;
using RRRSRoguelike.Enums;
using RRRSRoguelike.Entities;
using RRRSRoguelike.Helpers;
using RRRSRoguelike.Helpers.Visualizer;
using RRRSRoguelike.Screens;
#endregion

namespace RRRSRoguelike.Managers
{
	/// <summary>
	/// Initializes the managers needed to run the game and maintains the state of the current game.
	/// </summary>
	class GameManager
	{

		#region variables
		public Random DungeonBuilderRandom;
		public Random MonsterRandom;
		public Random GeneralRandom;

		public Dungeon Dungeon = new Dungeon();
		public DungeonScreen DungeonScreen;
		public bool GodMode;



		//Managers
		public CreatureManager CreatureManager;
		public PropManager PropManager;
		public SoundManager SoundManager = new SoundManager();
		public ActionManager ActionManager;
		public Visualizer DungeonVisualizer;

		//Flags
		private int currentDungeonLevel = 1;
		public bool gameOver = false;
		public bool Redraw = false;

		//Screens

		#endregion

		#region singleton
		//This pattern allows the manager to be initialized and used as a static.  Lovely.
		static readonly GameManager instance = new GameManager();

		public static GameManager Instance
		{
			get { return instance; }
		}
		#endregion

		#region properties

		/// <summary>
		/// Holds the currentlevel.  Very important
		/// </summary>
		public int CurrentDungeonLevel
		{
			get { return currentDungeonLevel; }
			set { currentDungeonLevel = value; }
		}

		public DungeonLevel DungeonLevel
		{
			get { return Dungeon.Levels[currentDungeonLevel - 1]; }
			set { Dungeon.Levels[currentDungeonLevel - 1] = value; }
		}

		public bool? PlayerHasWon
		{
			get { return CreatureManager.PlayerAlive && !IsGameActive; }
		}

		//read only flag
		public bool IsGameActive
		{
			get { return (CreatureManager.Player.Hits > 0 && !gameOver); }
		}

		public Dictionary<string, string> Texts
		{
			get { return Dungeon.Data.Texts; }
		}

		#endregion

		#region methods

		/// <summary>
		/// Initialize all the managers and set the flags
		/// </summary>
		/// 
        public void Initialize()
		{
            if (SessionVars.UserPickedSeed)
            {
                DungeonBuilderRandom = new Random(SessionVars.Seed);
                MonsterRandom = new Random(SessionVars.Seed);
            }
            else
            {
                SessionVars.SetSeed();
                DungeonBuilderRandom = new Random(SessionVars.Seed);
                MonsterRandom = new Random(SessionVars.Seed);
            }

			currentDungeonLevel = 1;
			gameOver = false;

			InitializeManagers();

		}
			
		/// <summary>
		/// Does what is says on the tin.
		/// </summary>
		public void InitializeManagers()
		{
			//TODO: If you code a new manager don't forget to add it here.
			SoundManager = new SoundManager();

			CreatureManager = new CreatureManager();
			PropManager = new PropManager();

			ActionManager = new ActionManager();
			ActionManager.Initialize(Enum.GetNames(typeof(Actions)).Length);
			
			DungeonVisualizer = new Visualizer();

		}


		//This visual stuff doesn't belong here.

		/// <summary>
		/// This is used to give the user a visual cue if something has changed but won't be updated in time/at all.
		/// </summary>
		public void ForceRedraw()
		{
			Redraw = true;
			DrawDungeon();
		}

		/// <summary>
		/// Prepares tiles and calls the visualizer
		/// </summary>
		public void DrawDungeon()
		{
			if (Redraw)
			{
				SetAllDungeonObjectsToTiles();
				DungeonVisualizer.Visualize(DungeonLevel, false);
				//this is used to reduce the number of redraws, reducing flicker.
				Redraw = false;
			}
		}

		/// <summary>
		/// This currently calls the separate manager to turn their entities into tiles for drawing.
		/// </summary>
		private void SetAllDungeonObjectsToTiles()
		{
			DungeonLevel.Clear();
			PropManager.PropsToTiles();
			CreatureManager.CreaturesToTiles();
		}

		/// <summary>
		/// Makes the Soundmanager call cleaner in other classes.
		/// </summary>
		/// <param name="sound"></param>
		public void PlaySound(SoundList sound)
		{
			Instance.SoundManager.PlaySound(sound.ToString());
		}

		public static void NextLevel()
		{
			Instance.CurrentDungeonLevel++;

			Instance.Dungeon.Levels.Add(new DungeonLevel(Instance.CurrentDungeonLevel, Constants.DungeonWidth, Constants.DungeonHeight));
			Instance.DungeonLevel.CreateRandomDungeonObjects();

			Instance.CreatureManager.NewLevel();
			Instance.ForceRedraw();
		}

        #endregion
	}
}
